package com.glgc.projecti.common;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;

public abstract class BusService {

	protected Logger logger = Logger.getLogger(this.getClass());

	private String PROTACOL = "https";
	private String REMOTE_IP = "61.160.69.110";
	private int REMOTE_PORT = 443;
	
//	private String PROTACOL = "http";
//	private String REMOTE_IP = "help.glsc.com.cn";
//	private int REMOTE_PORT = 80;
	
	private String busAppuser;
	private String busSecret;
	
	
	public abstract List<NameValuePair> fillParaSendMsg();
	
	public String accessBus()
			throws URISyntaxException, UnsupportedEncodingException,
			NoSuchAlgorithmException, KeyManagementException, IOException,
			ClientProtocolException {
		HttpPost httpPost = createUrlTemplate(fillParaSendMsg());

		HttpClient httpclient = null;
		if (getPROTACOL().equals("https")) {
			httpclient = createHttpsClient();
		} else if (getPROTACOL().equals("http")){
			httpclient = createHttpClient();
		}
		
		HttpResponse httpResponse = httpclient.execute(httpPost);

		String results = readResponse(httpResponse);
		logger.info("access bus result: " + results);
		return results;
	}
	
	private HttpClient createHttpClient() {
		HttpClient httpclient = new DefaultHttpClient();
		return httpclient;
	}

	private HttpClient createHttpsClient() throws NoSuchAlgorithmException,
			KeyManagementException {
		HttpClient httpclient = new DefaultHttpClient();
		SSLContext ctx = SSLContext.getInstance("SSL");
		X509TrustManager tm = new X509TrustManager() {

			public void checkClientTrusted(X509Certificate[] xcs, String string)
					throws CertificateException {

			}

			public void checkServerTrusted(X509Certificate[] xcs, String string)
					throws CertificateException {
			}

			public X509Certificate[] getAcceptedIssuers() {
				return null;
			}
		};
		ctx.init(null, new TrustManager[] { tm }, null);
		SSLSocketFactory ssf = new SSLSocketFactory(ctx,
				SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

		ClientConnectionManager ccm = httpclient.getConnectionManager();
		SchemeRegistry sr = ccm.getSchemeRegistry();
		sr.register(new Scheme(getPROTACOL(), getREMOTE_PORT(), ssf));
		return httpclient;
	}

	private HttpPost createUrlTemplate(List<NameValuePair> functionQparams)
			throws URISyntaxException, UnsupportedEncodingException {

		List<NameValuePair> qparams = new ArrayList<NameValuePair>();

		qparams.add(new BasicNameValuePair("secret", getBusSecret()));
		qparams.add(new BasicNameValuePair("appid", getBusAppuser()));

		qparams.addAll(functionQparams);

		qparams.add(new BasicNameValuePair("time", System.currentTimeMillis()
				+ ""));
		qparams.add(new BasicNameValuePair("signature",
				generateSignature(qparams)));
		qparams.remove(0); // 生成密文后去掉secret项， 该项不传
		URI uri = createUri();

		HttpPost httpPost = new HttpPost(uri);
		httpPost.setEntity(new UrlEncodedFormEntity(qparams, "UTF-8"));
		return httpPost;
	}

	private URI createUri() throws URISyntaxException {
		URI uri = new URI(getPROTACOL(), null, getREMOTE_IP(), getREMOTE_PORT(),
				"/ProxyApi/ProxyApiServlet", null, null);
		return uri;
	}

	private String readResponse(HttpResponse httpResponse) {
		BufferedReader bufferedReader = null;
		StringBuilder entityStringBuilder = new StringBuilder();
		int statusCode = httpResponse.getStatusLine().getStatusCode();
		if (statusCode == HttpStatus.SC_OK) {
			HttpEntity httpEntity = httpResponse.getEntity();
			if (httpEntity != null) {
				try {
					bufferedReader = new BufferedReader(new InputStreamReader(
							httpEntity.getContent(), "UTF-8"), 8 * 1024);
					String line = null;
					while ((line = bufferedReader.readLine()) != null) {
						entityStringBuilder.append(line + "\n");
					}
					return entityStringBuilder.toString();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	private String generateSignature(List<NameValuePair> qparams) {
		List<String> value_list = new ArrayList<String>();

		for (NameValuePair pair : qparams) {
			value_list.add(pair.getValue());

		}
		String[] to_sort = value_list.toArray(new String[value_list.size()]);
		try {
			return sha1Hex(to_sort);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	private String sha1Hex(String[] data) throws UnsupportedEncodingException {
		Arrays.sort(data);// 按字母顺序排序数组
		return DigestUtils.sha1Hex(StringUtils.join(data).getBytes("UTF-8"));
	}

	public String getPROTACOL() {
		return PROTACOL;
	}

	public String getREMOTE_IP() {
		return REMOTE_IP;
	}

	public int getREMOTE_PORT() {
		return REMOTE_PORT;
	}

	public String getBusAppuser() {
		return busAppuser;
	}

	public String getBusSecret() {
		return busSecret;
	}
}
